package ltd.jdsoft.cute.channel.interceptor;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;

import ltd.jdsoft.cute.channel.exception.ChannelExceptionEnum;
import ltd.jdsoft.cute.channel.helper.PublicKeyHelper;
import ltd.jdsoft.cute.channel.model.OrgIPConfig;
import ltd.jdsoft.cute.channel.model.Orgnization;
import ltd.jdsoft.cute.channel.service.OrgIPConfigService;
import ltd.jdsoft.cute.channel.service.OrgnizationService;
import ltd.jdsoft.cute.channel.util.CommonParams;
import ltd.jdsoft.cute.common.rsa.RSAHelper;
import ltd.jdsoft.cute.common.session.SecuritySession;
import ltd.jdsoft.cute.common.util.StatusType;
import ltd.jdsoft.cute.spring.web.exception.BizException;
import ltd.jdsoft.cute.spring.web.util.NetUtils;

/**
 * 对接入方进行拦截器验证，包括公共参数、接入方状态以及签名验证等。
 * 
 * @author zhengzhq
 *
 */
@Component
public class OrgAccessInterceptor implements HandlerInterceptor {

  private static Logger logger = LoggerFactory.getLogger(OrgAccessInterceptor.class);
  @Autowired
  private OrgnizationService orgnizationService;
  @Autowired
  private OrgIPConfigService orgIPConfigService;

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    CommonParams.validate(request);

    // 验证接入方身份
    Orgnization orgnization =
        orgnizationService.getByCooperator(request.getParameter(CommonParams.COOPERATOR));
    if (orgnization == null) {
      logger.warn("un recognized cooperator! request parameters: {}",
          JSONObject.toJSONString(request.getParameterMap()));
      throw new BizException(ChannelExceptionEnum.UN_RECOGNIZED_COOPERATOR);
    }
    if (orgnization.getStatus() != StatusType.ENABLE) {
      throw new BizException(ChannelExceptionEnum.ORG_DISABLED);
    }

    // 验证签名状态
    if (!RSAHelper.verifySign(formatSignData(request), request.getParameter(CommonParams.SIGN),
        PublicKeyHelper.getPublicKey(orgnization))) {
      throw new BizException(ChannelExceptionEnum.SIGN_ERROR);
    }

    // 如果不是debug模式，那么需要检验ip的合法性
    if (!orgnization.isDebug()) {
      String ip = NetUtils.getRemoteIp(request);
      OrgIPConfig orgIPConfig = orgIPConfigService.get(orgnization.getId(), ip);
      if (orgIPConfig == null) {
        logger.warn("ip {} access denied!", ip);
        throw new BizException(ChannelExceptionEnum.IP_DEFIED);
      }
    }

    SecuritySession.set(orgnization);

    return true;
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {

  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
      Object handler, Exception ex) throws Exception {
    // 请求结束的时候本地线程清空保存的用户信息
    SecuritySession.clearOnOver();
  }

  /**
   * 首先按照参数的字母顺序排序，然后拼接成a=b&c=d的数据格式返回，拼接串不包括sign参数
   * 
   * @param request
   * @return
   */
  private String formatSignData(HttpServletRequest request) {
    StringBuilder builder = new StringBuilder();
    Map<String, String[]> parameterTreeMap = new TreeMap<>(request.getParameterMap());
    Iterator<String> parameterNameIt = parameterTreeMap.keySet().iterator();
    while (parameterNameIt.hasNext()) {
      String parameterName = parameterNameIt.next();
      if (parameterName.equals(CommonParams.SIGN)) {
        continue;
      }
      String value = request.getParameter(parameterName);
      if (builder.length() > 0) {
        builder.append("&");
      }
      builder.append(parameterName).append("=").append(value);
    }

    return builder.toString();
  }
}
